package com.mercycrazy.springframework.beans.factory.support;

import com.mercycrazy.springframework.beans.BeansException;
import com.mercycrazy.springframework.beans.factory.FactoryBean;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 对 FactoryBean 进行管理
 *
 * @author <a href="mailto:1443424326@qq.com">mercycrazy</a>
 * @since 2022-11-27
 */
public class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {

    // Cache of Singleton objects created by FactoryBeans: FactoryBean name -> object
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>();

    protected Object getCachedObjectForFactoryBean(String beanName) {
        Object object = factoryBeanObjectCache.get(beanName);
        return object != NULL_OBJECT ? object : null;
    }

    protected Object getObjectFromFactoryBean(FactoryBean<?> factoryBean, String beanName) {
        if (factoryBean.isSingleton()) {
            Object object = factoryBeanObjectCache.get(beanName);
            if (object == null) {
                object = doGetObjectFromFactoryBean(factoryBean, beanName);
                factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT);
            }
            return object != NULL_OBJECT ? object : null;
        } else {
            return doGetObjectFromFactoryBean(factoryBean, beanName);
        }
    }

    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factoryBean, final String beanName) {
        try {
            return factoryBean.getObject();
        } catch (Exception e) {
            throw new BeansException("FactoryBean throws exception on object[" + beanName + "] creation", e);
        }
    }
}
